package com.warrior.superdata.util;


import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author Francis.Yang
 */
@Slf4j
public class BeanHelper {

    public static <T> T copyProperties(Object source, Class<T> target){
        try {
            T t = target.newInstance();
            BeanUtils.copyProperties(source, t);
            return t;
        } catch (Exception e) {
            log.error("【数据转换】数据转换出错，目标对象{}构造函数异常", target.getName(), e);
            throw new RuntimeException("数据转换出错");
        }
    }

    public static <T> List<T> copyWithCollection(List<?> sourceList, Class<T> target){
        try {
            return sourceList.stream().map(s -> copyProperties(s, target)).collect(Collectors.toList());
        } catch (Exception e) {
            log.error("【数据转换】数据转换出错，目标对象{}构造函数异常", target.getName(), e);
            throw new RuntimeException("数据转换出错");        }
    }

    public static <T> Set<T> copyWithCollection(Set<?> sourceList, Class<T> target){
        try {
            return sourceList.stream().map(s -> copyProperties(s, target)).collect(Collectors.toSet());
        } catch (Exception e) {
            log.error("【数据转换】数据转换出错，目标对象{}构造函数异常", target.getName(), e);
            throw new RuntimeException("数据转换出错");        }
    }


    public static Map convertToMap(Object obj){
        if(obj == null)
            return null;
        Map map = new HashMap();
        try
        {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor propertyDescriptors[] = beanInfo.getPropertyDescriptors();
            PropertyDescriptor apropertydescriptor[] = propertyDescriptors;
            int i = apropertydescriptor.length;
            for(int j = 0; j < i; j++){
                PropertyDescriptor property = apropertydescriptor[j];
                String key = property.getName();
                if(!key.equals("class")){
                    Method getter = property.getReadMethod();
                    Object value = getter.invoke(obj, new Object[0]);
                    map.put(key, value);
                }
            }

        }
        catch(Exception e)
        {
            System.out.println((new StringBuilder()).append("transBean2Map Error ").append(e).toString());
        }
        return map;
    }


    /**
     * list的深拷贝
     * @param src
     * @param <T>
     * @return
     * @throws ClassNotFoundException
     */
    public static <T> List<T> deepCopy(List<T> src) {
        try {
            ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
            ObjectOutputStream out = new ObjectOutputStream(byteOut);
            out.writeObject(src);

            ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
            ObjectInputStream in = new ObjectInputStream(byteIn);
            @SuppressWarnings("unchecked")
            List<T> dest = (List<T>) in.readObject();
            return dest;
        }
        catch (Exception e){
            e.printStackTrace();
            log.error("[{}]",e);
            return null;
        }
    }


}
